Golang 对称加密算法
时间:2022-10-21 | 分类:编程笔记>Golang

对称加密算法是使用同一个密钥進行加密和解密的方法,常见的对称加密算法有:DES,3DES,AES,RC2,RC4, RC5。下面用golang来实现DES、3DES和AES加密算法。
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"encoding/base64"
"errors"
"fmt"
)
func main() {
//DES密钥 8个字节
key := "12345678"
//3DES密钥 24个字节
//key = "abcdefig12345678gifedcba"
//AES密钥,key长度:16、24、32 bytes 对应 AES-128、AES-192、AES-256
//key = "abcdefig12345678"
keyBytes := []byte(key)
strBytes := []byte("要加密的内容")
fmt.Println("原数据:", strBytes)
//进行加密
cipherArr, err := SCEncrypt(strBytes, keyBytes, "DES")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("加密后的数据:", cipherArr)
oringinalBytes, err := SCDecrypt(cipherArr, keyBytes, "DES")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("解密后的数据:", oringinalBytes)
fmt.Println("\n==========字符串方式加解密")
str := "要加密的内容2"
fmt.Println("原始数据:", str)
cipherText, err := SCEncryptString(str, key, "DES")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("加密后的数据:", cipherText)
oringinalText, err := SCDecryptString(cipherText, key, "DES")
if err != nil {
fmt.Println(err)
return
}
fmt.Println("解密后的数据:", oringinalText)
}
//对称加密算法 (原数据, 密钥, 加密类型)
func SCEncrypt(oringinalBytes, key []byte, scType string) ([]byte, error) {
//1、实例化一个密码器block数据类型,(参数为密钥)
var err error
var block cipher.Block
switch scType {
case "DES":
block, err = des.NewCipher(key)
case "3DES":
block, err = des.NewTripleDESCipher(key)
case "AES":
block, err = aes.NewCipher(key)
}
if err != nil {
return nil, errors.New(fmt.Sprintf("密码器创建失败:%s", err))
}
//要填充的区块个数
blockSize := block.BlockSize()
//2、对明文填充(参数为原始字节和密码对象的区块个数)
paddingBytes := PKCS5Pading(oringinalBytes, blockSize)
fmt.Println("填充后的字节:", paddingBytes)
//3、实例化CBC加密模式(参数为密码器和密钥)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
fmt.Println("加密模式:", blockMode)
//4、对填充后的明文字节加密(参数为加密字节和填充字节)
cipherBytes := make([]byte, len(paddingBytes)) //用于接收加密后的字节
blockMode.CryptBlocks(cipherBytes, paddingBytes)
return cipherBytes, nil
}
//对称解密 (加密数据, 密钥, 加密类型)
func SCDecrypt(cipherBytes, key []byte, scType string) ([]byte, error) {
//1、实例化一个密码器block数据类型,(参数为密钥)
var err error
var block cipher.Block
switch scType {
case "DES":
block, err = des.NewCipher(key)
case "3DES":
block, err = des.NewTripleDESCipher(key)
case "AES":
block, err = aes.NewCipher(key)
}
if err != nil {
return nil, errors.New(fmt.Sprintf("密码器创建失败:%s", err))
}
//要填充的区块个数
blockSize := block.BlockSize()
//2、实例化CBC解密模式(参数为密码器和密钥)
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
fmt.Println("解密模式:", blockMode)
//3、对加密数据进行解密(参数为加密字节和填充字节)
paddingBytes := make([]byte, len(cipherBytes)) //用于接收解密后的字节
blockMode.CryptBlocks(paddingBytes, cipherBytes)
//4、去除填充的字节后获取到原数据
originalBytes := PKCS5UnPading(paddingBytes)
return originalBytes, nil
}
//字符串方式加密
func SCEncryptString(originalText, key, scType string) (string, error) {
cipherBytes, err := SCEncrypt([]byte(originalText), []byte(key), scType)
if err != nil {
return "", nil
}
//把加密后的数据用base64编码为字符串
base64str := base64.StdEncoding.EncodeToString(cipherBytes)
return base64str, nil
}
//字符串方式解密
func SCDecryptString(cipherText, key, scType string) (string, error) {
cipherBytes, _ := base64.StdEncoding.DecodeString(cipherText)
cipherBytes, err := SCDecrypt(cipherBytes, []byte(key), scType)
if err != nil {
return "", nil
}
return string(cipherBytes), nil
}
//填充字节函数
//数字填充方式
func PKCS5Pading(data []byte, blockSize int) []byte {
//填充内容 根据bolckSize的大小减去原始数据长度取余数
pading := blockSize - len(data)%blockSize
fmt.Println("要填充的字节:", pading)
//将pading转换为数组
arr1 := []byte{byte(pading)}
//要填充pading的个数
arr2 := bytes.Repeat(arr1, pading)
//返回填充后的数组
return append(data, arr2...)
}
//零位填充
func ZerosPading(data []byte, blockSize int) []byte {
//填充内容 根据bolckSize的大小减去原始数据长度取余数
pading := blockSize - len(data)%blockSize
fmt.Printf("要填充%d个0\n", pading)
//填充0的数组
arr := bytes.Repeat([]byte{0}, pading)
//返回填充后的数组
return append(data, arr...)
}
//去除填充字节函数
//去除数字填充
func PKCS5UnPading(data []byte) []byte {
//获取最后一个元素,也就是要去除的数量
unPading := data[len(data)-1]
//去除填充后的数组
result := data[:(len(data) - int(unPading))]
return result
}
//去除零位填充
func ZerosUnPadding(data []byte) []byte {
//把右侧的部分全部截取掉
return bytes.TrimRightFunc(data, func(r rune) bool {
return r == 0
})
}